/*================================================================================
*
*
*                                   
*
*
* 项目名称: mcp2515-spi-can-demo
* 文件名称: mcp2515.c
* 创建日期: 20-12-21
* 文件描述: 
*
================================================================================*/
#include "mcp2515.h"

//-private data------------------------------------------------------------------
//-SPI INTERFACE-
static void s_mcpSPI_Rst(void);
static void s_mcpSPI_Rd(uint8_t u8Addr, uint8_t *pdata, uint8_t u8Num);
static void s_mcpSPI_RdRB(uint8_t MCP_INST_RD_RBxx, uint8_t *pdata, uint8_t u8Num);
static void s_mcpSPI_Wr(uint8_t u8Addr, const uint8_t *pdata, uint8_t u8Num);
static void s_mcpSPI_LdTB(uint8_t MCP_INST_LD_TBxx, const uint8_t *pdata, uint8_t u8Num);
static void s_mcpSPI_RTS(uint8_t MCP_INST_RTS_TBn);
static uint8_t s_u8mcpSPI_RdStat(void);
static uint8_t s_u8mcpSPI_RxStat(void);
static void s_mcpSPI_BitMdf(uint8_t u8Addr, uint8_t u8Msk, uint8_t u8Data);

//-private code------------------------------------------------------------------

//-public data-------------------------------------------------------------------
uint8_t MCP2515ErrState; //错误标志寄存器值
uint8_t MCP2515ITState; //中断挂起标志位

//-SPI INTERFACE-----------------------------------------------------------------
//- SPI INSTRUCTION SET -
#define MCP_INST_RESET                  0xC0

#define MCP_INST_READ                   0x0C
#define MCP_INST_RD_RB                  0x90
#define MCP_INST_RD_RB0SIDH             (MCP_INST_RD_RB|(0<<1)) //Start at RXB0SIDH
#define MCP_INST_RD_RB0D0               (MCP_INST_RD_RB|(1<<1)) //Start at RXB0D0
#define MCP_INST_RD_RB1SIDH             (MCP_INST_RD_RB|(2<<1)) //Start at RXB1SIDH
#define MCP_INST_RD_RB1D0               (MCP_INST_RD_RB|(3<<1)) //Start at RXB0D0

#define MCP_INST_WRITE                  0x02
#define MCP_INST_LD_TB                  0x40
#define MCP_INST_LD_TB0SIDH             (MCP_INST_LD_TB|0) //Start at TXB0SIDH
#define MCP_INST_LD_TB0D0               (MCP_INST_LD_TB|1) //Start at TB0D0
#define MCP_INST_LD_TB1SIDH             (MCP_INST_LD_TB|2) //Start at TXB1SIDH
#define MCP_INST_LD_TB1D0               (MCP_INST_LD_TB|3) //Start at TB1D0
#define MCP_INST_LD_TB2SIDH             (MCP_INST_LD_TB|4) //Start at TXB2SIDH
#define MCP_INST_LD_TB2D0               (MCP_INST_LD_TB|5) //Start at TB2D0

#define MCP_INST_RTS                    0x80 //Message Request-to-Send
#define MCP_INST_RTS_TB0                (MCP_INST_RTS|0x01) //Request-to-Send for TXB0
#define MCP_INST_RTS_TB1                (MCP_INST_RTS|0x02) //Request-to-Send for TXB1
#define MCP_INST_RTS_TB2                (MCP_INST_RTS|0x04) //Request-to-Send for TXB2

#define MCP_INST_RD_STAT                0xA0
#define MCP_INST_RX_STAT                0xB0

#define MCP_INST_BIT_MDF                0x05

/********************************************************************************
*函数功能: 
    使用SPI复位MCP2515芯片
*修改记录: 
*日期:                作者:                摘要:
      20-12-21             YummoShin            Create
********************************************************************************/
static void s_mcpSPI_Rst(void)
{
    MCP_SPI_CS_LO();
    MCP_SPI_WR(MCP_INST_RESET);
    MCP_SPI_CS_HI();
}

/********************************************************************************
*函数功能:
    SPI读寄存器数据指令
    @param u8Addr, 寄存器起始地址
    @param pdata, 放置数据指针
    @param u8Num, 读取寄存器数量
*修改记录: 
*日期:                作者:                摘要:
      20-12-21             YummoShin            Create
********************************************************************************/
static void s_mcpSPI_Rd(uint8_t u8Addr, uint8_t *pdata, uint8_t u8Num)
{
    MCP_SPI_CS_LO();
    MCP_SPI_WR(MCP_INST_READ);
    MCP_SPI_WR(u8Addr);
    MCP_SPI_RD(pdata, u8Num);
    MCP_SPI_CS_HI();
}

/********************************************************************************
*函数功能: 
    SPI读取RX BUFFER指令
    @param MCP_INST_RD_RBxx, 读RB 命令
        @arg MCP_INST_RD_RB0SIDH
        @arg MCP_INST_RD_RB0D0
        @arg MCP_INST_RD_RB1SIDH
        @arg MCP_INST_RD_RB1D0
    @param pdata, 放置数据指针
    @param u8Num, 读取数量
*修改记录: 
*日期:                作者:                摘要:
      20-12-21             YummoShin            Create
********************************************************************************/
static void s_mcpSPI_RdRB(uint8_t MCP_INST_RD_RBxx, uint8_t *pdata, uint8_t u8Num)
{
    MCP_SPI_CS_LO();
    MCP_SPI_WR(MCP_INST_RD_RBxx);
    MCP_SPI_RD(pdata, u8Num);
    MCP_SPI_CS_HI();
}

/********************************************************************************
*函数功能: 
    SPI写寄存器数据指令
    @param u8Addr, 寄存器起始地址
    @param pdata, 放置数据指针
    @param u8Num, 读取寄存器数量
*修改记录: 
*日期:                作者:                摘要:
      20-12-21             YummoShin            Create
********************************************************************************/
static void s_mcpSPI_Wr(uint8_t u8Addr, const uint8_t *pdata, uint8_t u8Num)
{
    MCP_SPI_CS_LO();
    MCP_SPI_WR(MCP_INST_WRITE);
    MCP_SPI_WR(u8Addr);
    MCP_SPI_WR_BURST(pdata, u8Num);
    MCP_SPI_CS_HI();
}

/********************************************************************************
*函数功能: 
    SPI 写TX BUFFER指令
    @param MCP_INST_LD_TBxx, 写 TB 指令
        @arg MCP_INST_LD_TB0SIDH
        @arg MCP_INST_LD_TB0D0
        @arg MCP_INST_LD_TB1SIDH
        @arg MCP_INST_LD_TB1D0
        @arg MCP_INST_LD_TB2SIDH
        @arg MCP_INST_LD_TB2D0
    @param pdata, 待写入数据指针
    @param u8Num, 写入数据数量
*修改记录: 
*日期:                作者:                摘要:
      20-12-21             YummoShin            Create
********************************************************************************/
static void s_mcpSPI_LdTB(uint8_t MCP_INST_LD_TBxx, const uint8_t *pdata, uint8_t u8Num)
{
    MCP_SPI_CS_LO();
    MCP_SPI_WR(MCP_INST_LD_TBxx);
    MCP_SPI_WR_BURST(pdata, u8Num);
    MCP_SPI_CS_HI();
}

/********************************************************************************
*函数功能: 
    请求发送TB命令
    @param 请求发送TB命令
        @arg MCP_INST_RTS, commend will be ignored
        @arg MCP_INST_RTS_TB0
        @arg MCP_INST_RTS_TB1
        @arg MCP_INST_RTS_TB2
*修改记录: 
*日期:                作者:                摘要:
      20-12-21             YummoShin            Create
********************************************************************************/
static void s_mcpSPI_RTS(uint8_t MCP_INST_RTS_TBn)
{
    MCP_SPI_CS_LO();
    MCP_SPI_WR(MCP_INST_RTS_TBn);
    MCP_SPI_CS_HI();
}

/********************************************************************************
*函数功能: 
    SPI 获取寄存器标志状态
    @retval u8Stat, SPI读取的标志状态
*修改记录: 
*日期:                作者:                摘要:
      20-12-21             YummoShin            Create
********************************************************************************/
static uint8_t s_u8mcpSPI_RdStat(void)
{
    uint8_t u8Stat=0;

    MCP_SPI_CS_LO();
    MCP_SPI_WR(MCP_INST_RD_STAT);
    MCP_SPI_RD(&u8Stat, 1);
    MCP_SPI_CS_HI();

    return u8Stat;
}

/********************************************************************************
*函数功能: 
    SPI 读取RX STATUS
    @retval u8RxStat, 读取的 RX STATUS
*修改记录: 
*日期:                作者:                摘要:
      20-12-21             YummoShin            Create
********************************************************************************/
static uint8_t s_u8mcpSPI_RxStat(void)
{
    uint8_t u8RxStat=0;

    MCP_SPI_CS_LO();
    MCP_SPI_WR(MCP_INST_RX_STAT);
    MCP_SPI_RD(&u8RxStat, 1);
    MCP_SPI_CS_HI();

    return u8RxStat;
}

/********************************************************************************
*函数功能: 
    SPI Bit Modify指令模式操作寄存器
    @param u8Addr, 可做BIT MODIFY配置的地址
        @arg BFPCTRL
        @arg TXRTSCTRL
        @arg CANCTRL
        @arg CNF3
        @arg CNF2
        @arg CNF1
        @arg CANINTE
        @arg CANINTF
        @arg EFLG
        @arg TXB0CTRL
        @arg TXB1CTRL
        @arg TXB2CTRL
        @arg RXB0CTRL
        @arg RXB1CTRL
    @param u8Msk, mask
    @param u8Data, data
*修改记录: 
*日期:                作者:                摘要:
      20-12-21             YummoShin            Create
********************************************************************************/
static void s_mcpSPI_BitMdf(uint8_t u8Addr, uint8_t u8Msk, uint8_t u8Data)
{
    MCP_SPI_CS_LO();
    MCP_SPI_WR(MCP_INST_BIT_MDF);
    MCP_SPI_WR(u8Addr);
    MCP_SPI_WR(u8Msk);
    MCP_SPI_WR(u8Data);
    MCP_SPI_CS_HI();
}

//-MESSAGE TRANSMISSION----------------------------------------------------------
//-以TBn为基地址获取TBn相关的寄存器地址，TBn可为 MCP_TXB0, MCPTXB1, MCP_TXB2
#define TXBnCTRL(TBn)               (TBn+0)
#define TXBnSIDH(TBn)               (TBn+1)
#define TXBnSIDL(TBn)               (TBn+2)
#define TXBnEID8(TBn)               (TBn+3)
#define TXBnEID0(TBn)               (TBn+4)
#define TXBnDLC(TBn)                (TBn+5)
#define TXBnDx(TBn, Dx)             (TBn+6+Dx) //Dx 为 0/1/2/3/4/5/6/7

/********************************************************************************
*函数功能: 
    以寻址的方式装载TX BUFF
        @param MCP_TXBn, 发送BUFFER
            @arg MCP_TXB0
            @arg MCP_TXB1
            @arg MCP_TXB2
        @param pMsg, 待装载CAN帧指针
*修改记录: 
*日期:                作者:                摘要:
      20-12-21             YummoShin            Create
********************************************************************************/
void MCP2515WrMsg2Buf(uint8_t MCP_TXBn, const McpCanFrm_t *pMsg)
{
    uint8_t u8Tmp[13]={0};
    uint8_t u8DLC=pMsg->u8DLC;
    uint8_t i;

    if(u8DLC>8) u8DLC = 8; //DLC可大于8但只发送8个DATA

    u8Tmp[0] = ((pMsg->u16SID)&0x07F8>>3); //TXBnSIDH
    u8Tmp[1] = ((pMsg->u16SID)&0x0007<<5) | ((pMsg->u8IDE)&0x01<<3) | ((pMsg->u32EID)&0x30000>>16); //TXBnSIDL
    u8Tmp[2] = ((pMsg->u32EID)&0xFF00>>8); //TXBnEID8
    u8Tmp[3] = ((pMsg->u32EID)&0xFF); //TXBnEID0
    u8Tmp[4] = ((pMsg->u8RTR)&0x01<<6) | ((pMsg->u8DLC)&0x0F); //TXBnDLC

    for(i=0; i<u8DLC; i++) //TXBnDm
    {
        u8Tmp[i+5] = (pMsg->u8Data)[i];
    }

    s_mcpSPI_Wr(TXBnSIDH(MCP_TXBn), u8Tmp, 5+u8DLC);
}

/********************************************************************************
*函数功能: 
    以指令的方式装载TX BUFF
        @param MCP_TXBn, 发送BUFFER
            @arg MCP_TXB0
            @arg MCP_TXB1
            @arg MCP_TXB2
        @param pMsg, 待装载CAN帧指针
*修改记录: 
*日期:                作者:                摘要:
      20-12-22             YummoShin            Create
********************************************************************************/
void MCP2515LdMsg2Buf(uint8_t MCP_TXBn, const McpCanFrm_t *pMsg)
{
    uint8_t u8Tmp[13];
    uint8_t u8DLC=pMsg->u8DLC;
    uint8_t i;
    uint8_t u8INST_LD_TBn=0;

    u8INST_LD_TBn = (MCP_TXBn/16-3)*2 | MCP_INST_LD_TB; //计算MCP_INST_LD_TBnSIDH

    if(u8DLC>8) u8DLC = 8; //DLC可大于8但只发送8个DATA

    u8Tmp[0] = ((pMsg->u16SID)&0x07F8>>3); //TXBnSIDH
    u8Tmp[1] = ((pMsg->u16SID)&0x0007<<5) | ((pMsg->u8IDE)&0x01<<3) | ((pMsg->u32EID)&0x30000>>16); //TXBnSIDL
    u8Tmp[2] = ((pMsg->u32EID)&0xFF00>>8); //TXBnEID8
    u8Tmp[3] = ((pMsg->u32EID)&0xFF); //TXBnEID0
    u8Tmp[4] = ((pMsg->u8RTR)&0x01<<6) | ((pMsg->u8DLC)&0x0F); //TXBnDLC

    for(i=0; i<u8DLC; i++) //TXBnDm
    {
        u8Tmp[i+5] = (pMsg->u8Data)[i];
    }

    s_mcpSPI_LdTB(u8INST_LD_TBn, u8Tmp, 5+u8DLC);
}

/********************************************************************************
*函数功能: 
    设定TX BUFFER优先级
    @param MCP_TXBn, TX BUFF
        @arg MCP_TXB0
        @arg MCP_TXB1
        @arg MCP_TXB2
    @param MCP_TXP_LVLn, TX BUFF priority
        @arg MCP_TXP_LVL0
        @arg MCP_TXP_LVL1
        @arg MCP_TXP_LVL2
        @arg MCP_TXP_LVL3
*修改记录: 
*日期:                作者:                摘要:
      20-12-22             YummoShin            Create
********************************************************************************/
void MCP2515SetTxPri(uint8_t MCP_TXBn, uint8_t MCP_TXP_LVLn)
{
    s_mcpSPI_BitMdf(MCP_TXBn, 0x03, MCP_TXP_LVLn);
}

/********************************************************************************
*函数功能: 
    SPI 请求发送 Request-to-Send
    @param MCP_TXBn, 发送BUFFER
        @arg MCP_TXB0
        @arg MCP_TXB1
        @arg MCP_TXB2
*修改记录: 
*日期:                作者:                摘要:
      20-12-22             YummoShin            Create
********************************************************************************/
void MCP2515RTS(uint8_t MCP_TXBn)
{
    uint8_t MCP_INST_RTS_TBn=0;

    MCP_INST_RTS_TBn = 1<<(MCP_TXBn/16-3) |MCP_INST_RTS;

    s_mcpSPI_RTS(MCP_INST_RTS_TBn);
}

/********************************************************************************
*函数功能: 
    使能One-shot Mode
*修改记录: 
*日期:                作者:                摘要:
      20-12-22             YummoShin            Create
********************************************************************************/
void MCP2515EnableOSM(void)
{
    s_mcpSPI_BitMdf(CANCTRL, 0x80, 0x80);
}

/********************************************************************************
*函数功能: 
    失能One-shot Mode
*修改记录: 
*日期:                作者:                摘要:
      20-12-22             YummoShin            Create
********************************************************************************/
void MCP2515DisableOSM(void)
{
    s_mcpSPI_BitMdf(CANCTRL, 0x80, 0);
}

/********************************************************************************
*函数功能: 
    配置TXnRTS PIN模式
    @param MCP_TXBn, 配置对应的TX BUFFER
        @arg MCP_TXB0
        @arg MCP_TXB1
        @arg MCP_TXB2
    @param MCP2515_RTS_PIN_MODx, 模式
        @arg MCP_RTS_PIN_MOD_DIG_IP
        @arg MCP_RTS_PIN_MOD_DIG_IP
*修改记录: 
*日期:                作者:                摘要:
      20-12-23             YummoShin            Create
********************************************************************************/
void MCP2515SetRtsPinMode(uint8_t MCP_TXBn, eMCPRtsPinMod MCP2515_RTS_PIN_MODx)
{
    uint8_t u8Msk=1<<(MCP_TXBn/16-3);
    uint8_t u8Data=MCP2515_RTS_PIN_MODx<<(MCP_TXBn/16-3);

    s_mcpSPI_BitMdf(TXRTSCTRL, u8Msk, u8Data);
}

/********************************************************************************
*函数功能: 
    获取TXnRTS PIN状态
    @param MCP_TXBn, TX BUFFER
        @arg MCP_TXB0
        @arg MCP_TXB1
        @arg MCP_TXB2
    @retval BnRTS, 位状态
*修改记录: 
*日期:                作者:                摘要:
      20-12-23             YummoShin            Create
********************************************************************************/
uint8_t u8MCP2515GetRtsPinVal(uint8_t MCP_TXBn)
{
    uint8_t BnRTS=0;
    uint8_t u8Tmp=0;

    s_mcpSPI_Rd(TXRTSCTRL, &u8Tmp, 1);
    BnRTS = (u8Tmp>>(MCP_TXBn/16))&1;
    
    return BnRTS;
}

/********************************************************************************
*函数功能: 
    通过清零TXBnCTRL.TXREQ中止传输请求
    @param MCP_TXBn
        @arg MCP_TXB0
        @arg MCP_TXB1
        @arg MCP_TXB2
*修改记录: 
*日期:                作者:                摘要:
      20-12-23             YummoShin            Create
********************************************************************************/
void MCP2515AbortTx(uint8_t MCP_TXBn)
{
    s_mcpSPI_BitMdf(MCP_TXBn, 0x08, 0);
}

//-MESSAGE RECEPTION-------------------------------------------------------------

/********************************************************************************
*函数功能: 
    按RX BUFFER读取CAN消息帧
    @param MCP_RXBn
        @arg MCP_RXB0
        @arg MCP_RXB1
    @param pMsg, CAN消息指针
*修改记录: 
*日期:                作者:                摘要:
      20-12-24             YummoShin            Create
********************************************************************************/
void MCP2515GetMsg(uint8_t MCP_RXBn, McpCanFrm_t *pMsg)
{
    uint8_t u8Data[13] = {0};
    uint8_t MCP_INST_RD_RBnSIDH=(MCP_RXBn/16-6)*2|MCP_INST_RD_RB;
    uint8_t i=0;

    s_mcpSPI_RdRB(MCP_INST_RD_RBnSIDH, u8Data, 13);
    pMsg->u16SID = (u8Data[0]<<3) | ((u8Data[1]&0xE0)>>5);
    pMsg->u8IDE = (u8Data[1]>>3&0x01);
    pMsg->u32EID = pMsg->u8IDE ? ((u8Data[1]&0x03)<<16 | (u8Data[2]<<8) | u8Data[3]) : (0);
    pMsg->u8RTR = pMsg->u8IDE ?  (u8Data[4]>>6&0x01) : (u8Data[1]>>4&0x01);
    pMsg->u8DLC = u8Data[4]&0x0F;
    for(i=0; i<8; i++)
    {
        pMsg->u8Data[0] = u8Data[i+5];
    }
}

/********************************************************************************
*函数功能: 
    RX STATUS指令获取接收状态，并赋值给RX STATUS结构体
    @param pRxStat, RX STATUS 结构体指针
*修改记录: 
*日期:                作者:                摘要:
      20-12-24             YummoShin            Create
********************************************************************************/
void MCP2515GetMatchFLT(McpRxStat_t *pRxStat)
{
    uint8_t u8Tmp=0;

    u8Tmp = s_u8mcpSPI_RxStat();

    pRxStat->u8RcvdMsg = u8Tmp>>6&0x03;
    pRxStat->u8MsgTyp = u8Tmp>>3&0x03;
    pRxStat->u8FltMtch = u8Tmp&0x07;
}

/********************************************************************************
*函数功能: 
    使能滚存
*修改记录: 
*日期:                作者:                摘要:
      20-12-24             YummoShin            Create
********************************************************************************/
void MCP2515EnableROV(void)
{
    s_mcpSPI_BitMdf(RXB0CTRL, 0x04, 0x04);
}

/********************************************************************************
*函数功能: 
    失能滚存
*修改记录: 
*日期:                作者:                摘要:
      20-12-24             YummoShin            Create
********************************************************************************/
void MCP2515DisableROV(void)
{
    s_mcpSPI_BitMdf(RXB0CTRL, 0x04, 0);
}

/********************************************************************************
*函数功能: 
    设定 RX BUFFER 工作模式
    @param MCP_RXBn, RX BUFFER
        @arg MCP_RXB0
        @arg MCP_RXB1
    @param MCP_RXMn, RB Operation Mode
        @arg MCP_RXM0
        @arg MCP_RXM1
        @arg MCP_RXM2
        @arg MCP_RXM3
*修改记录: 
*日期:                作者:                摘要:
      20-12-24             YummoShin            Create
********************************************************************************/
void MCP251SetRXM(uint8_t MCP_RXBn, uint8_t MCP_RXMn)
{
    s_mcpSPI_BitMdf(MCP_RXBn, 0x60, MCP_RXMn<<5);
}

/********************************************************************************
*函数功能: 
    设置RX PINs模式
    @param MCP_RXBn
        @arg MCP_RXB0
        @arg MCP_RXB1
    @param MCP_RXP_MODx
        @arg MCP_RXP_MOD_RXNE_INT
        @arg MCP_RXP_MOD_DIG_OUT0
        @arg MCP_RXP_MOD_DIG_OUT1
*修改记录: 
*日期:                作者:                摘要:
      20-12-25             YummoShin            Create
********************************************************************************/
void MCP2515SetRxPinMode(uint8_t MCP_RXBn, uint8_t MCP_RXP_MODx)
{
    uint8_t u8Msk=0x11<<(MCP_RXBn/16-6);
    uint8_t u8Data=MCP_RXP_MODx<<(MCP_RXBn/16-6);
    
    s_mcpSPI_BitMdf(BFPCTRL, u8Msk, u8Data);
}

/********************************************************************************
*函数功能: 
    使能RX1BF Pin Function
*修改记录: 
*日期:                作者:                摘要:
      20-12-25             YummoShin            Create
********************************************************************************/
void MCP2515EnalbeRxPin(uint8_t MCP_RXBn)
{
    uint8_t u8Msk=1<<(MCP_RXBn/16-6);
    s_mcpSPI_BitMdf(BFPCTRL, u8Msk, u8Msk);
}
/********************************************************************************
*函数功能: 
    失能RX1BF Pin Function
*修改记录: 
*日期:                作者:                摘要:
      20-12-25             YummoShin            Create
********************************************************************************/
void MCP2515DisalbeRxPin(uint8_t MCP_RXBn)
{
    uint8_t u8Msk=1<<(MCP_RXBn/16-6);
    s_mcpSPI_BitMdf(BFPCTRL, u8Msk, 0);
}

/********************************************************************************
*函数功能: 
    设置滤波器的值，只有在配置模式才可设置
    @param MCP_RXFn, 滤波器
        @arg MCP_RXF0
        @arg MCP_RXF1
        @arg MCP_RXF2
        @arg MCP_RXF3
        @arg MCP_RXF4
        @arg MCP_RXF5
    @param pFilter, 滤波器参数指针
*修改记录: 
*日期:                作者:                摘要:
      20-12-25             YummoShin            Create
********************************************************************************/
void MCP2515SetRxFlt(uint8_t MCP_RXFn, const McpRxFlt_t *pFilter)
{
    uint8_t u8Data[4]={0};

    u8Data[0] = pFilter->u16SID>>3;
    u8Data[1] = pFilter->u16SID<<5 | pFilter->u8EXIDE<<3 | pFilter->u32EID>>16;
    u8Data[2] = pFilter->u32EID>>8&0xFF;
    u8Data[3] = pFilter->u32EID&0xFF;

    s_mcpSPI_Wr(MCP_RXFn, u8Data, 4);
}

/********************************************************************************
*函数功能: 
    设置掩码,只有在配置模式才可设置
        @param MCP_RXMn, 掩码
            @arg MCP_RXM0
            @arg MCP_RXM1
        @param pMask, 掩码参数指针
*修改记录: 
*日期:                作者:                摘要:
      20-12-25             YummoShin            Create
********************************************************************************/
void MCP2515SetRxMsk(uint8_t MCP_RXMn, const McpRxMsk_t *pMask)
{
    uint8_t u8Data[4]={0};

    u8Data[0] = pMask->u16SID>>3;
    u8Data[1] = pMask->u16SID<<5 | pMask->u32EID>>16;
    u8Data[2] = pMask->u32EID>>8&0xFF;
    u8Data[3] = pMask->u32EID&0xFF;


    s_mcpSPI_Wr(MCP_RXMn, u8Data, 4);
}

//-BIT TIMING--------------------------------------------------------------------

/********************************************************************************
*函数功能: 
    配置BIT TIMEING,PS2由PHSEG22:PHSEG20决定
    @param pBitTime, 位时间结构体指针
*修改记录: 
*日期:                作者:                摘要:
      20-12-27             YummoShin            Create
********************************************************************************/
void MCP2515CfgBitTime(McpBitTime_t *pBitTime)
{
    uint8_t u8Data[3]={0};

    s_mcpSPI_Rd(CNF3, u8Data, 2); //读取CNF3、CNF2原先的值
    u8Data[0] &= 0xC0; //取出保留BTLMODE, SAM位
    u8Data[1] &= 0xC0; //取出保留SOF, WAKFIL位

    u8Data[0] |= pBitTime->u8PHSEG2;
    u8Data[1] |= pBitTime->u8PHSEG1<<3 | pBitTime->u8PRSEG | 0x80;
    u8Data[3] = pBitTime->u8BRP<<6 | pBitTime->u8BRP;
    s_mcpSPI_Wr(CNF3, u8Data, 3);
}

/*******************************************
BTLMODE, SAM, SOF, WAKFIL相关函数还未实现
********************************************/

//-ERROR DETECTION---------------------------------------------------------------
/********************************************************************************
*函数功能: 
    读取错误寄存器标志，赋值给全局变量 MCP2515ErrState
*修改记录: 
*日期:                作者:                摘要:
      20-12-29             YummoShin            Create
********************************************************************************/
void MCP2515RdEFLG(void)
{
    s_mcpSPI_Rd(EFLG, &MCP2515ErrState, 1);
}

//-INTERRUPTS--------------------------------------------------------------------

/********************************************************************************
*函数功能: 
    Get and return Interrupt Code Bits
    @retval ICOD<2:0>
*修改记录: 
*日期:                作者:                摘要:
      20-12-30             YummoShin            Create
********************************************************************************/
uint8_t u8MCP2515GetICOD(void)
{
    uint8_t u8Rtn=0;

    s_mcpSPI_Rd(CANSTAT, &u8Rtn, 1);

    u8Rtn >>= 1;

    return u8Rtn;
}

/********************************************************************************
*函数功能: 
    按位使能MCP2515中断，可用算数或运算同时使能多个中断位
    @param MCP_IT_x
        @arg MCP_IT_RX0
        @arg MCP_IT_RX1
        @arg MCP_IT_TX0
        @arg MCP_IT_TX1
        @arg MCP_IT_TX2
        @arg MCP_IT_ERR
        @arg MCP_IT_WAK
        @arg MCP_IT_MERR
*修改记录: 
*日期:                作者:                摘要:
      20-12-30             YummoShin            Create
********************************************************************************/
void MCP2515EnableIT(eMcpITBit MCP_IT_x)
{
    s_mcpSPI_BitMdf(CANINTE, MCP_IT_x, 0xFF);
}

/********************************************************************************
*函数功能: 
    按位失能MCP2515中断，可用算数或运算同时失能多个中断位
    @param MCP_IT_x
        @arg MCP_IT_RX0
        @arg MCP_IT_RX1
        @arg MCP_IT_TX0
        @arg MCP_IT_TX1
        @arg MCP_IT_TX2
        @arg MCP_IT_ERR
        @arg MCP_IT_WAK
        @arg MCP_IT_MERR
*修改记录: 
*日期:                作者:                摘要:
      20-12-30             YummoShin            Create
********************************************************************************/
void MCP2515DisableIT(eMcpITBit MCP_IT_x)
{
    s_mcpSPI_BitMdf(CANINTE, MCP_IT_x, 0);
}

/********************************************************************************
*函数功能: 
    读取 CANINTE 寄存器的值
    @retval CANINITE寄存器的值
*修改记录: 
*日期:                作者:                摘要:
      20-12-30             YummoShin            Create
********************************************************************************/
uint8_t u8MCP2515RdCANINTE(void)
{
    uint8_t u8Rtn=0;

    s_mcpSPI_Rd(CANINTE, &u8Rtn, 1);

    return u8Rtn;
}

/********************************************************************************
*函数功能: 
    获取中断标志位寄存器参数并赋值
*修改记录: 
*日期:                作者:                摘要:
      20-12-30             YummoShin            Create
********************************************************************************/
void MCP2515RdITFLG(void)
{
    s_mcpSPI_Rd(CANINTF, &MCP2515ITState, 1);
}

/********************************************************************************
*函数功能: 
    清除中断标志位，可用算数或运算同时失能多个中断位
    @param MCP_IT_x
        @arg MCP_IT_RX0
        @arg MCP_IT_RX1
        @arg MCP_IT_TX0
        @arg MCP_IT_TX1
        @arg MCP_IT_TX2
        @arg MCP_IT_ERR
        @arg MCP_IT_WAK
        @arg MCP_IT_MERR
*修改记录: 
*日期:                作者:                摘要:
      21-02-04             YummoShin            Create
********************************************************************************/
void MCP2515ClrITFLG(eMcpITBit MCP_IT_x)
{
    s_mcpSPI_BitMdf(CANINTF, MCP_IT_x, 0);
}

//-OSCILLATOR--------------------------------------------------------------------

/********************************************************************************
*函数功能: 
    使能或禁止时钟时钟输出，并配置时钟分频
    @param State, 1:enable, 0:disable
    @param MCP_CLKPRE
        @arg MCP_CLKPRE1
        @arg MCP_CLKPRE2
        @arg MCP_CLKPRE4
        @arg MCP_CLKPRE8
*修改记录: 
*日期:                作者:                摘要:
      21-01-01             YummoShin            Create
********************************************************************************/
void MCP2515ClkoutCfg(uint8_t State, uint8_t MCP_CLKPRE)
{
    uint8_t u8Data=(State<<2)|MCP_CLKPRE;

    s_mcpSPI_BitMdf(CANCTRL, 0x07, u8Data);
}

//-MODES OF OPERATION------------------------------------------------------------

/********************************************************************************
*函数功能: 
    配置MCP2515操作模式
    @param MCP_REQOPx
        @arg MCP_REQOP_NORMAL
        @arg MCP_REQOP_SLEEP
        @arg MCP_REQOP_LOOPBACK
        @arg MCP_REQOP_LISTEN
        @arg MCP_REQOP_CONFIG
*修改记录: 
*日期:                作者:                摘要:
      21-01-01             YummoShin            Create
********************************************************************************/
void MCP2515SetMode(uint8_t MCP_REQOPx)
{
    uint8_t u8Data=MCP_REQOPx<<5;

    s_mcpSPI_BitMdf(CANCTRL, 0xE0, u8Data);
}

/********************************************************************************
*函数功能: 
    获取当前MCP2515操作模式
    @retval MCP_REQOPx, 当前模式
        @arg MCP_REQOP_NORMAL
        @arg MCP_REQOP_SLEEP
        @arg MCP_REQOP_LOOPBACK
        @arg MCP_REQOP_LISTEN
        @arg MCP_REQOP_CONFIG
*修改记录: 
*日期:                作者:                摘要:
      21-01-01             YummoShin            Create
********************************************************************************/
uint8_t u8MCP2515GetMode(void)
{
    uint8_t u8Rtn=0;

    s_mcpSPI_Rd(CANSTAT, &u8Rtn, 1);
    u8Rtn >>= 5;

    return u8Rtn;
}
